﻿@page "/workflowlogs"

@using Gurux.DLMS.AMI.Shared.DIs

@using Gurux.DLMS.AMI.Shared.Enums
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Gurux.DLMS.AMI.Shared.DTOs
@using Gurux.DLMS.AMI.Shared.Rest
@using Microsoft.AspNetCore.SignalR.Client
@using Gurux.DLMS.AMI.Shared
@using Gurux.DLMS.AMI.Client.Helpers
@using Gurux.DLMS.AMI.Module

@attribute [Authorize(Roles = "Admin, WorkflowLogManager")]
@inject NavigationManager NavigationManager
@inject HttpClient Http
@inject ConfirmBase Confirm
@inject IGXNotifier2 Notifier
@implements IDisposable

<PageTitle>@Properties.Resources.WorkflowLogs</PageTitle>

    <AuthorizeView Roles=@GXRoles.ToString(GXRoles.Admin, GXRoles.WorkflowLogManager)>
        <MenuControl RightCorner="true">
            <ChildContent>
                <MenuItem Text="@Properties.Resources.Close" Icon="oi oi-pencil" OnClick="@OnClose" />
                <MenuItem Text="@Properties.Resources.Clear" Icon="oi oi-trash" OnClick="@OnClear" />
            </ChildContent>
        </MenuControl>
    </AuthorizeView>

    <GXTable @ref="table"
             Context="error"
             ItemsProvider="@GetItems"
             SelectionMode="SelectionMode.Multiple"
             ShowRemoved="false"
             Filter="@Filter"
             ShowAllUsers="@Header"
             Columns="@Columns"
             CanEdit="@CanEdit"
             OnSearch="@Updated">
        <FilterContent>
            <th>
                <input class="form-control" placeholder="按创建时间..."
                       type="datetime-local"
                       @onchange="@((ChangeEventArgs __e) => filter.CreationTime = @StatusTile.ToDateTime(__e.Value))" />
            </th>
            <th>
                <input class="form-control" type="text" placeholder="@Properties.Resources.FilterByError"
                       @onchange="@((ChangeEventArgs __e) => filter.Message = Convert.ToString(__e.Value))" />
            </th>
            <th>
                <div>
                    <input class="form-control" type="text" placeholder="@Properties.Resources.FilterByLevel"
                           @onchange="@((ChangeEventArgs __e) => filter.Level = @ClientHelpers.LevelToInt(__e.Value))" />
                </div>
            </th>
            <th>
                <input class="form-control" placeholder="按关闭时间..."
                       type="datetime-local"
                       @onchange="@((ChangeEventArgs __e) => filter.Closed = @StatusTile.ToDateTime(__e.Value))" />
            </th>
        </FilterContent>
        <MenuContent>
            <ContextMenuItem Text="@Properties.Resources.Show" Icon="oi oi-eye" OnClick="@OnShow"></ContextMenuItem>
            <ContextMenuItem Text="@Properties.Resources.Close" Icon="oi oi-pencil" OnClick="@OnClose"></ContextMenuItem>
        </MenuContent>
        <HeaderContent>
            <Th Id="CreationTime" SortMode="SortMode.Descending">@Properties.Resources.CreationTime</Th>
            <th>@Properties.Resources.Error</th>
        <Th Id="Level">@Properties.Resources.Level</Th>
            <Th Id="Closed">@Properties.Resources.CloseTime</Th>
        </HeaderContent>
        <ItemContent>
            <Td Link="@("Config/WorkflowLog/Edit/" + error.Id)">@error.CreationTime</Td>
            <td>@error.Message</td>
        <td>@ClientHelpers.LevelToString(error.Level)</td>
        <td>@error.Closed</td>
    </ItemContent>
</GXTable>
<br />
<Confirm @ref="ClearConfirmation" ConfirmationChanged="OnClearConfirmation"
         ConfirmationTitle=@Properties.Resources.ConfirmDataClear
         AllowDelete="false"
         OkTitle="@Properties.Resources.Clear"
         ConfirmationMessage="@Properties.Resources.AreYouSureYouWantToClearLog">
</Confirm>
<Confirm @ref="CloseConfirmation"
         ConfirmationChanged="OnCloseConfirmation" ConfirmationTitle="Confirm close"
         AllowDelete="false"
         OkTitle="@Properties.Resources.Close"
         ConfirmationMessage="@Properties.Resources.AreYouSureYouWantToCloseSelectedItems">
</Confirm>

@code {

    /// <summary>
    /// Selected schedule ID.
    /// </summary>
    [Parameter]
    public Guid? Id { get; set; }

    /// <inheritdoc />
    public string Name
    {
        get
        {
            return Gurux.DLMS.AMI.Client.Properties.Resources.WorkflowLogs;
        }
    }

    /// <inheritdoc />
    public Type? ConfigurationUI
    {
        get
        {
            return null;
        }
    }

    /// <inheritdoc />
    public string? Icon
    {
        get
        {
            return "oi oi-tablet";
        }
    }

    /// <summary>
    /// Amount of the workflow log shown on the view.
    /// </summary>
    [Parameter]
    public int Count { get; set; } = 0;

    /// <summary>
    /// Is filter shown.
    /// </summary>
    [Parameter]
    public bool Filter { get; set; } = true;

    /// <summary>
    /// Is header shown.
    /// </summary>
    [Parameter]
    public bool Header { get; set; } = true;

    /// <summary>
    /// Is edit allowed.
    /// </summary>
    [Parameter]
    public bool CanEdit { get; set; } = true;

    /// <summary>
    /// Available columns.
    /// </summary>
    [Parameter]
    public string[]? Columns { get; set; }

    /// <summary>
    /// Is title shown.
    /// </summary>
    [Parameter]
    public bool Title { get; set; } = true;

    /// <summary>
    /// Workflow log filter.
    /// </summary>
    private GXWorkflowLog filter = new GXWorkflowLog();
    /// <summary>
    /// User is verified before workflow log are cleared.
    /// </summary>
    protected ConfirmBase? ClearConfirmation;

    /// <summary>
    /// User is verified before workflow logs are closed.
    /// </summary>
    protected ConfirmBase? CloseConfirmation;

    /// <summary>
    /// Closed errors are shown.
    /// </summary>
    public bool ShowClosedErrors { get; set; }

    /// <summary>
    /// Get active item.
    /// </summary>
    public GXWorkflowLog? Active
    {
        get
        {
            return table?.Active;
        }
    }

    /// <summary>
    /// Table reference.
    /// </summary>
    protected GXTable<GXWorkflowLog>? table;

    /// <summary>
    /// Update table.
    /// </summary>
    protected async Task Updated()
    {
        try
        {
            if (table != null)
            {
                Notifier.ClearStatus();
                await table.RefreshDataAsync(true);
            }
        }
        catch (Exception ex)
        {
            Notifier.ProcessError(ex);
        }
    }

    protected override void OnInitialized()
    {
        Notifier.ProgressStart();
        Notifier.ClearStatus();
        try
        {
            if (Notifier == null)
            {
                throw new ArgumentException(Properties.Resources.InvalidNotifier);
            }
            Notifier.On<IEnumerable<GXWorkflow>?>(this, nameof(IGXHubEvents.ClearWorkflowLogs), async (errors) =>
            {
                await Updated();
            });
            Notifier.On<IEnumerable<GXWorkflowLog>>(this, nameof(IGXHubEvents.AddWorkflowLogs), async (errors) =>
            {
                await Updated();
            });
            Notifier.On<IEnumerable<GXWorkflowLog>>(this, nameof(IGXHubEvents.CloseWorkflowLogs), async (errors) =>
            {
                await Updated();
            });
            Notifier.Clear();
            Notifier.UpdateButtons();
            if (table != null && Id != null)
            {
                //Get last selected item.
                table.Active = new GXWorkflowLog() { Id = Id.Value };
            }
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        catch (Exception ex)
        {
            Notifier.ProcessError(ex);
        }
        finally
        {
            Notifier.ProgressEnd();
        }
    }

    private async ValueTask<ItemsProviderResult<GXWorkflowLog>> GetItems(GXItemsProviderRequest request)
    {
        //Don't clear status or error is lost.
        Notifier.ProgressStart();
        try
        {
            if (ShowClosedErrors)
            {
                //Show closed errors.
                filter.Closed = DateTimeOffset.MaxValue;
            }
            else
            {
                //Show active errors.
                filter.Closed = null;
            }
            ListWorkflowLogs req = new ListWorkflowLogs()
                {
                    Index = request.StartIndex,
                    Count = request.Count,
                    Filter = filter,
                    OrderBy = request.OrderBy,
                    Descending = request.Descending,
                    AllUsers = request.ShowAllUserData
                };
            if (Count != 0)
            {
                req.Count = Count;
            }
            var ret = await Http.PostAsJson<ListWorkflowLogsResponse>("api/WorkflowLog/List", req, request.CancellationToken);
            if (ret.Logs != null)
            {
                //Mark workflow logs as seen.
                await Notifier.Mark(Http, TargetType.WorkflowLog, ret.Logs.Max(s => s.CreationTime));
                return new ItemsProviderResult<GXWorkflowLog>(ret.Logs, ret.Count);
            }
        }
        catch (TaskCanceledException)
        {
            //Let the table component handle this.
            throw;
        }
        catch (Exception ex)
        {
            Notifier.ProcessError(ex);
        }
        finally
        {
            Notifier.ProgressEnd();
        }
        return default;
    }

    /// <summary>
    /// Show workflow log details.
    /// </summary>
    public void OnShow()
    {
        try
        {
            Notifier.ClearStatus();
            if (table?.Active == null)
            {
                throw new Exception(Gurux.DLMS.AMI.Client.Properties.Resources.NoItemIsSelected);
            }
            ClientHelpers.NavigateTo(NavigationManager, Notifier, "/WorkflowLog/Edit/" + table.Active.Id);
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        catch (Exception ex)
        {
            Notifier.ProcessError(ex);
        }
    }

    /// <summary>
    /// Close the selected error.
    /// </summary>
    public void OnClose()
    {
        try
        {
            if (table == null || !table.SingleOrDefault().Any())
            {
                throw new Exception(Gurux.DLMS.AMI.Client.Properties.Resources.NoItemIsSelected);
            }
            CloseConfirmation?.Show(table?.SingleOrDefault()?.Select(s => s.Message).ToArray());
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        catch (Exception ex)
        {
            Notifier.ProcessError(ex);
        }
    }

    /// <summary>
    /// Close the selected logs.
    /// </summary>
    public async Task OnCloseConfirmation(ConfirmArgs args)
    {
        try
        {
            if (table != null && args.Confirm)
            {
                CloseWorkflowLog req = new CloseWorkflowLog()
                    {
                        Logs = table.SingleOrDefault().Select(w => w.Id).ToArray()
                    };
                await Http.PostAsJson<CloseWorkflowLogResponse>("api/WorkflowLog/Close", req);
            }
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        catch (Exception ex)
        {
            Notifier.ProcessError(ex);
        }
    }


    public void Dispose()
    {
        Notifier.RemoveListener(this);
    }

    /// <summary>
    /// Clear the workflow log list.
    /// </summary>

    public void OnClear()
    {
        Notifier.ClearStatus();
        ClearConfirmation?.Show();
    }

    /// <summary>
    /// Clear the workflow log list.
    /// </summary>
    public async Task OnClearConfirmation(ConfirmArgs args)
    {
        try
        {
            if (args.Confirm)
            {
                await Http.PostAsJson<ClearWorkflowLogsResponse>("api/WorkflowLog/Clear", new ClearWorkflowLogs());
            }
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        catch (Exception ex)
        {
            Notifier.ProcessError(ex);
        }
    }
}
